package server

import (
	"edata-hub/pkg/raft"
	"encoding/json"
	"fmt"
	"strings"
)

func (m *Master) Optimizer(cmd raft.CommandEntry) ([]raft.CommandEntry, error) {
	cmds := make([]raft.CommandEntry, 0)
	if cmd.Name == CLUSTER_INSTALL {
		optCmds, _ := m.Optimize_CLUSTER_INSTALL(cmd)
		cmds = append(cmds, optCmds...)
	} else if cmd.Name == ROLE_START {
		optCmds, _ := m.Optimize_DATACOMP_START(cmd)
		cmds = append(cmds, optCmds...)
	} else if cmd.Name == ROLE_STOP {
		optCmds, _ := m.Optimize_DATACOMP_STOP(cmd)
		cmds = append(cmds, optCmds...)
	} else {
		cmds = append(cmds, cmd)
	}
	return cmds, nil
}

func (m *Master) Optimize_DATACOMP_START(cmd raft.CommandEntry) ([]raft.CommandEntry, error) {
	cmds := make([]raft.CommandEntry, 0)
	comp := cmd.Params["comp"]
	roles := cmd.Params["roles"]
	addr := cmd.Params["addr"]
	orderRoles := m.GenRoleOrder(comp, roles)
	for _, role := range orderRoles {
		dcs_params := make(map[string]string)
		dcs_params["clusterId"] = cmd.Params["clusterId"]
		dcs_params["addr"] = addr
		dcs_params["comp"] = comp
		dcs_params["role"] = role
		dcs_ce := raft.CommandEntry{
			Name:       ROLE_START,
			Params:     dcs_params,
			ExecStatus: 0,
		}
		cmds = append(cmds, dcs_ce)
	}
	return cmds, nil
}

func (m *Master) Optimize_DATACOMP_STOP(cmd raft.CommandEntry) ([]raft.CommandEntry, error) {
	cmds := make([]raft.CommandEntry, 0)
	comp := cmd.Params["comp"]
	roles := cmd.Params["roles"]
	addr := cmd.Params["addr"]
	orderRoles := m.GenRoleOrder(comp, roles)
	for _, role := range orderRoles {
		dcs_params := make(map[string]string)
		dcs_params["addr"] = addr
		dcs_params["comp"] = comp
		dcs_params["role"] = role
		dcs_ce := raft.CommandEntry{
			Name:       ROLE_STOP,
			Params:     dcs_params,
			ExecStatus: 0,
		}
		cmds = append(cmds, dcs_ce)
	}
	return cmds, nil
}

func (m *Master) Optimize_CLUSTER_INSTALL(cmd raft.CommandEntry) ([]raft.CommandEntry, error) {
	cmds := make([]raft.CommandEntry, 0)
	var policy Policy
	err := json.Unmarshal([]byte(cmd.Params["policy"]), &policy)
	if err != nil {
		return nil, err
	}
	ns := policy.Nodes
	/*-------------------------------------创建集群安装进度命令------------------------------------------------------*/
	pc_params := make(map[string]string)
	pc_params["clusterId"] = cmd.Params["clusterId"]
	pc_ce := raft.CommandEntry{
		Name:       PROGRESS_CREATION,
		Params:     pc_params,
		ExecStatus: 0,
	}
	cmds = append(cmds, pc_ce)
	/*-------------------------------------创建集群的命令-----------------------------------------------------------*/
	cc_params := make(map[string]string)
	cc_params["clusterId"] = cmd.Params["clusterId"]
	cc_params["name"] = policy.Name
	cc_params["type"] = policy.Type
	cc_params["comp"] = policy.Comp
	cc_params["[sa]mode"] = policy.Mode
	cc_ce := raft.CommandEntry{
		Name:       CLUSTER_CREATION,
		Params:     cc_params,
		ExecStatus: 0,
	}
	cmds = append(cmds, cc_ce)
	/*-------------------------------------创建集群节点的命令-------------------------------------------------------*/
	for _, n := range ns {
		nodeInfo := NodeInfo{
			Ip:       n.Addr,
			Hostname: n.Hostname,
			Auths:    n.Auths,
			Status:   0,
		}
		data, _ := json.Marshal(nodeInfo)
		cn_params := make(map[string]string)
		cn_params["clusterId"] = cmd.Params["clusterId"]
		cn_params["node"] = string(data)
		cn_ce := raft.CommandEntry{
			Name:       NODE_CREATION,
			Params:     cn_params,
			ExecStatus: 0,
		}
		cmds = append(cmds, cn_ce)
	}
	/*-----------------------------------创建节点中角色的命令--------------------------------------------------------*/
	for _, n := range ns {
		cr_params := make(map[string]string)
		cr_params["clusterId"] = cmd.Params["clusterId"]
		cr_params["ip"] = n.Addr
		cr_params["roles"] = strings.Join(n.Roles, ",")
		cr_ce := raft.CommandEntry{
			Name:       ROLE_CREATION,
			Params:     cr_params,
			ExecStatus: 0,
		}
		cmds = append(cmds, cr_ce)
	}
	/*----------------------------------远程传输系列命令------------------------------------------------------------*/
	for _, n := range ns {
		//传输worker的命令
		wt_params := make(map[string]string)
		wt_params["clusterId"] = cmd.Params["clusterId"]
		wt_params["addr"] = n.Addr
		wt_params["auths"] = n.Auths
		wt_ce := raft.CommandEntry{
			Name:       WORKER_TRANSPORT,
			Params:     wt_params,
			ExecStatus: 0,
		}

		//远程传输数据组件的命令
		dct_params := make(map[string]string)
		dct_params["clusterId"] = cmd.Params["clusterId"]
		dct_params["addr"] = n.Addr
		dct_params["auths"] = n.Auths
		dct_params["comp"] = policy.Comp
		dct_ce := raft.CommandEntry{
			Name:       DATACOMP_TRANSPORT,
			Params:     dct_params,
			ExecStatus: 0,
		}
		//生成环境变量的命令
		eg_params := make(map[string]string)
		eg_params["clusterId"] = cmd.Params["clusterId"]
		eg_params["addr"] = n.Addr
		eg_params["auths"] = n.Auths
		eg_params["comp"] = policy.Comp
		env_kvs := make([]string, len(policy.Config))
		index := 0
		for env_key, env_val := range policy.Config {
			env_kvs[index] = env_key + "=" + env_val
			index++
		}
		eg_params["env"] = strings.Join(env_kvs, "\n")
		eg_ce := raft.CommandEntry{
			Name:       ENV_GENERATION,
			Params:     eg_params,
			ExecStatus: 0,
		}
		//生成安装模式的命令
		mg_params := make(map[string]string)
		mg_params["clusterId"] = cmd.Params["clusterId"]
		mg_params["addr"] = n.Addr
		mg_params["auths"] = n.Auths
		mg_params["comp"] = policy.Comp
		mg_params["[sa]mode"] = policy.Mode
		mg_ce := raft.CommandEntry{
			Name:       MODE_GENERATION,
			Params:     mg_params,
			ExecStatus: 0,
		}
		//修改远程目录的权限
		chm_params := make(map[string]string)
		chm_params["clusterId"] = cmd.Params["clusterId"]
		chm_params["addr"] = n.Addr
		chm_params["auths"] = n.Auths
		chm_ce := raft.CommandEntry{
			Name:       CHMOD_ALL_COMPS,
			Params:     chm_params,
			ExecStatus: 0,
		}

		iw_params := make(map[string]string)
		iw_params["clusterId"] = cmd.Params["clusterId"]
		iw_params["addr"] = n.Addr
		iw_params["auths"] = n.Auths
		iw_ce := raft.CommandEntry{
			Name:       WORKER_START,
			Params:     iw_params,
			ExecStatus: 0,
		}
		//安装数据组件
		dci_params := make(map[string]string)
		dci_params["clusterId"] = cmd.Params["clusterId"]
		dci_params["addr"] = n.Addr
		dci_params["auths"] = n.Auths
		dci_params["comp"] = policy.Comp
		dci_ce := raft.CommandEntry{
			Name:       DATACOMP_INSTALL,
			Params:     dci_params,
			ExecStatus: 0,
		}
		cmds = append(cmds, wt_ce)
		cmds = append(cmds, dct_ce)
		cmds = append(cmds, eg_ce)
		cmds = append(cmds, mg_ce)
		cmds = append(cmds, chm_ce)
		cmds = append(cmds, iw_ce)
		cmds = append(cmds, dci_ce)
	}
	progress := make([]string, 0)
	for _, c := range cmds {
		if c.Name == PROGRESS_CREATION {
			continue
		}
		step := fmt.Sprintf("%s,0", m.RServer.CommandsDes[c.Name])
		progress = append(progress, step)
	}
	cmds[0].Params["progress"] = strings.Join(progress, "\n")
	return cmds, nil
}
